查看原文
其他

实战 | 在应用中使用 Compose Material 3

Android Android 开发者 2022-05-12

Material You 是下一代 Material Design 的发展方向,也是一种全新的设计愿景: 方便您打造个性化的样式设计、满足各种需求并自适应各种屏幕;Jetpack Compose 是用于构建原生 Android 界面的新款现代工具包,可以帮助您更快地构建更出色的应用。


  • Material You
    https://m3.material.io/

  • Jetpack Compose
    https://developer.android.google.cn/jetpack/compose


您可能对现有的 Compose Material 库十分了解,它基于 Material Design 2 规范,其中包括了 Material 主题、Material 组件和深色主题等功能。新的 Compose Material 3 Jetpack 库现已发布 Alpha 版,它基于 Material Design 3 规范,包括了更新后的主题、组件以及动态配色这类 Material You 个性化功能,旨在与新的 Android 12 视觉样式和系统界面相得益彰。接下来,我们将使用 Jetchat 来说明如何应用 Material Design 3 和 Material You。


  • Compose Material 3 Jetpack 库
    https://developer.android.google.cn/jetpack/androidx/releases/compose-material3

  • Jetchat
    https://github.com/android/compose-samples/tree/main/JetNews


如果您更喜欢通过视频了解此内容,请在此处查看:

‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍△‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍‍ 在应用中使用 Compose Material 3

  • Bilibili 视频链接
    https://www.bilibili.com/video/BV14i4y1f71K/


Jetchat 是一款使用 Jetpack Compose 构建的示例聊天应用,目前使用 Material Design 2 中的主题和组件。我们将在 Jetchat 中,应用由我们的设计人员提供的 Compose Material 3 库的更新,其中包括更广泛的色调颜色、对组件的最新更新,甚至包括动态配色以使应用更加个性化,从而使其更加美观。

△ Jetchat 应用

在开始前,我们首先要将 Material 3 的依赖项添加到模块的 build.gradle 文件中:

implementation 'androidx.compose.material3:material3:1.0.0-alpha01'


MaterialTheme



我们先来看看 MaterialTheme。现有的 MaterialTheme 可组合项是 Material Design 2 的实现,它通过调整颜色、排版和形状系统,可以在整个应用内实现对 Material 2 组件进行主题设置。我们为 Material Design 3 引入了新版本的 MaterialTheme,可以通过调整配色方案和排版系统对 Material 3 组件的主题进行设置,而更新 Shape 的功能也会在不久之后加入。

import androidx.compose.material3.MaterialTheme @Composablefun MaterialTheme ( colorScheme: ColorScheme, typography: Typography, // 更新 Shape 的功能即将到来 content: @Composable () -> Unit)

首先,我们看一下配色方案。Material Design 3 将颜色细分到特定名称的颜色槽中。比如 Material 3 组件使用的 Primary、Background 和 Error,这些颜色槽共同形成一种配色方案。部分颜色槽来自 Material Design 2,同时也引入了一些新的颜色槽以扩充整体调色板。这些颜色槽都包含了美观的全新默认基准颜色,在浅色和深色主题上都可以应用。

△ 绿色框为 Material You 中新加入的颜色槽

上面这些颜色取自一组色调调色板,例如,我们来看一下 Primary 颜色槽。该颜色槽使用的颜色值来自 Primary 色调调色板中的不同色调,并根据浅色和深色主题选择相应的色调,以满足无障碍功能要求。

△ Primary 颜色槽

Compose 使用新的 ColorScheme 类对此进行建模,其参数以 Material Design 3 配色方案中的颜色槽命名。您可以使用 lightColorScheme 函数创建具有浅色基准值的 ColorScheme 实例;也可以使用自定义颜色覆盖默认值,或者使用 darkColorScheme 设置深色默认基准值;您还可以使用 isSystemInDarkTheme 工具函数,根据系统设置在浅色和深色配色方案之间切换。

val AppLightColorScheme = lightColorScheme ( primary = Color(...), // secondary、tertiary 等等 // 具有浅色基准值的 ColorScheme 实例) val AppDarkColorScheme = darkColorScheme( // primary、secondary、tertiary 等等 // 具有深色基准值的 ColorScheme 实例 val dark = isSystemInDarkTheme()val colorScheme = if (dark) AppDarkColorScheme else AppLightColorScheme // 将 colorScheme 作为参数传递给 MaterialTheme。MaterialTheme ( colorScheme = colorScheme, // 字型) { // 应用内容}

接下来,我们来看看 Jetchat 的配色方案。Jetchat 的配色方案由 MaterialTheme Builder 工具生成,我们使用 Jetchat 品牌颜色中的蓝色和黄色作为 Primary 颜色、Secondary 颜色和 Tertiary 颜色的来源,生成了非常适合 Jetchat 的 Material 3 配色方案,其中涵盖了用于浅色和深色主题的颜色。Jetchat 所使用的品牌颜色取自 MaterialTheme Builder 工具生成的一组自定义色调调色板,下图中显示了 Primary 颜色,即蓝色的色调调色板,以及配色方案中匹配的 Primary 颜色槽。


△ MaterialTheme Builder 工具中生成的 Jetchat 配色方案

要实现 Jetchat 配色方案,首先使用 Color 类声明这些颜色。MaterialTheme Builder 工具还可以为您导出生成的代码。接下来,便可以使用相应的颜色值声明 Jetchat 浅色和深色配色方案。

// 来自名为'Blue'的色调调色盘的 Primary 颜色val Blue10 = Color (0xFF000965)val Blue20 = Color (0xFF00159E)val Blue30 = Color (0xFF0023DA)val Blue40 = Color (0xFF1E40FF)val Blue80 = Color (0xFFBBC3FF)val Blue90 = Color (0xFFDDE0FF) val JetchatLightColorScheme = lightColorScheme ( primary = Blue40, onPrimary = Color.White, primaryContainer = Blue90, onPrimaryContainer = Blue10, // secondary、tertiary、surface 等等) val JetchatDarkColorScheme = darkColorScheme ( primary = Blue80, onPrimary = Blue20, primaryContainer = Blue30, onPrimaryContainer = Blue90, // secondary、tertiary、surface 等等)

我们为 Jetchat 主题创建了一个新的可组合函数,该函数接收一个用于判断深色主题的参数和一个应用内容参数,从而使我们可以在 Jetchat 的浅色和深色配色方案之间切换。接下来,我们将 colorScheme 值和 content 传递给内部的 MaterialTheme 可组合项,这使我们能够封装 Jetchat 内容并为应用提供主题。

@Composablefun JetchatTheme ( dark: Boolean = isSystemInDarkTheme(), content: @Composable () -> Unit) { val colorScheme = if (dark) JetchatDarkColorScheme else JetchatLightColorScheme MaterialTheme ( colorScheme = colorScheme, content = content, )}

下面让我们看一下 Jetchat 对话界面,界面中的不同部分使用了配色方案中的不同颜色槽。例如,根据用户不同,消息头像的边框颜色使用 Primary 颜色或 Tertiary 颜色。这里使用 MaterialTheme.colorScheme 访问主题颜色值。

△ Jetchat 对话界面
@Composablefun Message(...) { val avatarBorderColor = if (isUserMe) {        MaterialTheme.colorScheme.primary } else { MaterialTheme.colorScheme.tertiary } ...}


动态配色



接下来,让我们来了解什么是动态配色。动态配色是 Material You 的重要部分,即用算法从用户的壁纸中提取自定义颜色并应用于应用和系统界面,您可将此作为起点来生成完整的浅色和深色配色方案。

△ Jetchat 的配色方案随用户设置的壁纸变化

动态配色可在 Android 12 及更高版本中使用,要在 Compose 中实现动态 ColorScheme,需要首先检查 Build.VERSION.SDK。如果动态配色可用,我们便可以设置动态 ColorScheme;如果不可用,则可以回退到像以前一样使用 lightColorScheme 或 darkColorScheme:

val dynamic = Build.VERSION.SOK_INT >= Build.VERSION_CODES.Sval colorScheme = if (dynamic) { val context = LocalContext.current    // 使用 dynamicLightColorScheme 函数创建具有浅色动态值的 ColorScheme 实例 // 或使用 dynamicDarkColorScheme 创建具有深色动态值的实例    // 传入 Context 以便从 Android 系统获取动态配色资源 if (dark) dynamiclightColorScheme(context) else dynamicDarkColorScheme(context)} else { // 使用 lightColorScheme 或者 darkColorScheme}

目前,Jetchat 一直在使用品牌的蓝色配色方案,但我们希望增加对基于壁纸的动态配色方案的支持,以配合用户的个性化调整。在本例中,色调调色板基于壁纸中的颜色生成,而动态配色方案则派生自这些色调调色板,其中包括用于浅色和深色主题的颜色。


为了在 Jetchat 中实现这一点,我们首先更新 JetchatTheme 为动态配色添加一个新参数,然后使用该动态配色参数设置动态 ColorScheme,或者在不可用时回退到品牌的蓝色配色方案。与前面一样将 colorScheme 值和 content 传递给内部的 MaterialTheme 可组合项。

@Composablefun JetchatTheme ( dark: Boolean = isSystemInDarkTheme (), dynamic: Boolean = Build. VERSION.SDK_INT >= Build.VERSION_CODES.S, content: @Composable () -> Unit) { // ColorScheme 配置以及 MaterialTheme val colorScheme = if (dynamic) { val context = LocalContext.current if (dark) dynamicDarkColorScheme(context) else dynamicLightColorScheme(context) } else { if (dark) JetchatDarkColor Scheme else Jetchat Light Color Scheme } MaterialTheme( colorScheme = colorScheme, content = content, )}

现在,在 Android 12 及更高版本上,Jetchat 界面可根据用户壁纸自动调整配色,无论是浅色主题还是深色主题都可提供适合品牌的美观体验。

△ 自动适配深浅色主题的动态配色


排版



现在我们已经了解了配色方案,接下来让我们来看看排版。Material Design 3 有了新的字体规格,包括了由 Material Design 2 适配而来的文本样式。样式的命名和分组简化为显示、大标题、标题、正文和标签;每个分组都有大号、中号和小号字体。

△ Material 3 与 Material 2 的字体样式分组

Compose 使用新的 Typography 类对字体规格进行建模,其参数以 Material Design 3 字体规格中的样式命名。我们可以使用 Roboto 基准值创建一个 Typography 实例,用自定义文本样式覆盖默认值,最后将 Typography 作为参数传递给 MaterialTheme。

import androidx.compose.material3.Typography class Typography ( val displayLarge: TextStyle, val displayMedium: TextStyle, val displaySmall: TextStyle, // headlineLarge、titleMedium、bodySmall 等等) val AppTypography = Typography ( bodyLarge = TextStyle(...), // displayLarge、titleMedium、labelSmall 等等 // 使用默认的 Roboto 基准值) MaterialTheme ( typography = AppTypography, // colorScheme) { //App content}

我们再来看看 Jetchat 的排版。设计人员为我们提供了新的品牌字体规格,用到了自定义字体 Montserrat 和 Karla:

△ Jetchat 所使用的字体规格

我们首先使用 FontFamily 类声明这些字体,该类将保存 Font 类的实例。我们可以使用字体资源 ID 和字体粗细构造 Font 类,然后使用 Typography 类声明 Jetchat 字体样式,并使用 TextStyle 类覆盖每个文本样式,包括我们的字体、字号、字体粗细等其他排版值。最后,同样的,将 Typography 作为参数传递给 MaterialTheme:
val MontserratFontFamily = FontFamily ( Font(R.font.montserrat_regular), Font(R.font montserrat_light, FontWeight Light), Font(R.font.montserrat_semibold, FontWeight. SemiBold)) val KarlaFontFamily = FontFamily ( Font(R.font.karla_regular), Font(R.font.karla_bold, FontWeight. Bold)) val JetchatTypography = Typography( bodyLarge = TextStyle( fontFamily = KarlaFontFamily, fontWeight = FontWeight. Normal, fontSize = 16.sp, lineHeight = 24.sp, letterSpacing = 0.15.sp ), // titleMedium、labelSmall 等等) MaterialTheme ( typography = JetchatTypography, // colorScheme、content)


我们来看一下 Jetchat 对话界面,界面中的每个部分使用了 Jetchat 字体规格中的不同文本样式。例如,消息中的联系人和时间戳,分别使用了 titleMedium 和 labelSmall 样式。它们通过 MaterialTheme.typography 表示访问主题字体值。
△ 对话界面的字体设置
@Composablefun Message(...) {    … Text (style = MaterialTheme.typography.titleMedium, ...) Text (style = MaterialTheme.typography.labelSmall, ...)}


  

高度



在了解了 Material 3 主题相关的更新后,接下来让我们看看 Material Design 另一个关键更新——高度。概括来说,Material 2 中使用阴影表示高度,而 Material 3 中改为使用色调颜色叠加层表示高度。这是一种区分容器和表面的新方式,增加色调高度会使色调变得更为突出。


在 Material 2 中高度叠加层是深色主题的一部分,在 Material 3 中也已更改为色调颜色叠加层。

△ M2 与 M3 中高度系统效果对比

我们以 Surface 组件为例,Surface 是用于支持大多数 Material 组件的可组合项,现有的 Surface 可组合项实现的是 Material Design 2 的高度系统。在 Material Design 2 中 Surface 接收一个 elevation 参数并处理深色主题中的阴影和叠加层渲染。我们为 Material Design 3 引入了新版 Surface,它接受一个 tonalElevation 参数,并会在浅色和深色主题中处理色调颜色叠加层渲染。让我们看看前后有何不同:

△ Material 2 中的 Surface

△ Material 3 中的 Surface



组件更新



Material 3 对许多组件进行了更新,比如按钮、应用栏、对话框、FAB 和导航组件。此类更新利用了新的 Material 3 主题设置值,并包含了对每个组件规范的最新更新。

△ Material 3 中更新的组件

例如 Material 2 中的 BottomNavigation。它符合 Material Design 2 规范,并接受 backgroundColor 和 elevation 等参数。在 Material 3 中该可组合项更名为 NavigationBar,它符合 Material Design 3 规范,其中的参数更改为 containerColor 和 tonalElevation,以更准确地反映各自的用途。
// Materail 2 中的 NavigationBarimport androidx.compose.material.BottomNavigation @Composablefun BottomNavigation ( // M2 默认值 backgroundColor: Color, elevation: Dp,) // Materail 3 中的 NavigationBarimport androidx.compose.material3.NavigationBar @Composablefun NavigationBar ( // M3 默认值 containerColor: Color, tonalElevation: Dp,)

△ 更新前后的样式改变
Compose Material 3 中的组件进行了很多更新,为了让您全面了解所有的组件以及它们的实现方式,我们更新了 Compose Material Catalog 应用,并新增了 Material 3 部分。请在 AOSP 上查看源代码在 Google Play 中下载该应用

  • 源代码
    https://cs.android.com/androidx/platform/frameworks/support/+/androidx-main:compose/integration-tests/material-catalog/

  • 在 Google Play 中下载该应用
    https://play.google.com/store/apps/details?id=androidx.compose.material.catalog


下面我们来看看 Jetchat 中的一个例子。在个人资料界面上有一个用于撰写消息的扩展 FAB,该组件已从 Material 2 更新为 Material 3 版本。这是 Material 2 版本的一个简单实现,使用了 ExtendedFloatingActionButton 可组合项,内部使用了 Icon 和 Text、可组合项以及自定义的 Primary 背景颜色。

import androidx.compose.material.ExtendedFloatingActionButtonimport androidx.compose.material.Iconimport androidx.compose.material.Text ExtendedFloatingActionButton( icon = { Icon(...) }, text = { Text(...) }, backgroundColor = MaterialTheme.colors.primary, ...)


Material 3 对该组件的更新如这里所示,可组合项的依赖导入已更改为 Material 3,我们使用更名后的 containerColor 参数和 Material 3 配色方案中的 Tertiary 颜色。

import androidx.compose.material3.ExtendedFloatingActionButtonimport androidx.compose.material3.Iconimport androidx.compose.material3.Text ExtendedFloatingActionButton( icon = { Icon(...) }, text = { Text(...) },    containerColor = MaterialTheme.colorScheme.tertiary, ...)



视觉效果



Material You 的某些方面来自新的 Android 12 视觉样式和系统界面,其中的两个重要变化是波纹和滚动效果。现在,波纹效果会在按下时使用细微的闪光照亮表面,滚动效果则会在滚动容器的边缘使用拉伸效果。实现这些更改不需要额外的工作,在 Compose Foundation 1.1 及更高版本的滚动容器可组合项中拉伸滚动默认处于开启状态;Android 12 上提供的闪光波纹适用于所有 Material 组件。
△ M2 与 M3 中的波纹效果
// 拉伸滚动// 适用于 LazyColumn、Lazy Row、LazyVerticalGrid 等组件// ComposeFoundation 1.1.0+ 可用 // 闪光波纹// 适用于所有 Material 2 和 Material 3 组件// Android 12+ 可用


与 Android View 的互操作性改进



与 Android 视图的互操作性是使用 Compose 开发应用的一个重要部分,我们已经在 Material 3 中进行了一些更新来支持这一点。MDC-AndroidCompose Theme Adapter 库是一款支持重用 Android XML 主题的 Material 组件,以方便我们在 Jetpack Compose 中设置主题。

https://material-components.github.io/material-components-android-compose-theme-adapter/


现有的 MdcTheme 可组合项与 Material 2 XML 主题兼容,我们还引入了一个新的 Mdc3Theme 可组合项,它与 Material 3 XML 主题兼容。

△ MDC-AndroidCompose Theme Adapter 是 XML 主题与 MaterialTheme 之间的桥梁


尾声



现在是在您的 Android 应用中试用 Compose Material 3 的好时机,我们准备了一系列资源来帮助您顺利完成旅程。我们提供了新的关于 Compose Material 3 的 API 文档,并在 Android Studio 中提供了新的 Empty Compose Activity 模板,其中包含有关 Material 3 的更新。此外,我们还更新了 Compose 中的主题设置指南,以及在前面看到的 Jetchat 示例和 Compose Material Catalog 应用,以及 MDC-Android ComposeTheme Adapter 互操作性库。


  • Compose Material 3 的 API 文档
    https://developer.android.google.cn/jetpack/androidx/releases/compose-material3

  • Compose 中的主题设置
    https://developer.android.google.cn/jetpack/compose/themes

  • Compose Material Catalog
    https://github.com/android/compose-samples
  • MDC-Android ComposeTheme Adapter
    https://material-components.github.io/material-components-android-compose-theme-adapter/



推荐阅读

如页面未加载,请刷新重试

 点击屏末 | 阅读原文 | 即刻了解 Material You 更多详情



除了通过触摸进行交互外,大屏幕设备还支持其他交互形式。设备的屏幕尺寸越大,用户就越有可能使用键盘、手写笔、鼠标、游戏手柄或其他外接设备。如果您想提高应用在这些情况下的易用性,可以计划支持其中一些输入方式,如需了解更多详情,请参阅文章:是时候为各式设备适配完善的输入支持了

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存